﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using YJKRevitKernel.ElementSearchUtility.LinkDocumentSuite;
using YJKInspectModel.ModelValidation.Commands;
using YJKInspectModel.ModelValidation.Utils;
using YJKPatternSign.StairsClearHeightDimension;
using YJKRevitStairs.StairsModel.CommonUnit;
using YJKRevitStairs.StairsModel.DataInfos;

namespace YJKInspectModel.ModelValidation.StairsRamp
{
	internal class StairsRampValidationManager
	{
		public StairsRampValidationManager(ExternalCommandData cmdData)
		{
			this.m_CmdData = cmdData;
			this.m_UIApp = cmdData.Application;
			this.m_UIDoc = this.m_UIApp.ActiveUIDocument;
			this.m_App = this.m_UIApp.Application;
			this.m_Doc = this.m_UIDoc.Document;
			this.m_listRampGroups = new List<List<RampResult>>();
			this.m_listStairsGroups = new List<List<StairsResult>>();
			this.m_ComponentTypeManager = new ComponentTypeManager(this.m_Doc);
		}

		public Result Validation(ref string message)
		{
			StairsRampValidationForm stairsRampValidationForm = new StairsRampValidationForm(this.m_ComponentTypeManager);
			if (stairsRampValidationForm.ShowDialog() != DialogResult.OK)
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			this.ValidationByProject(stairsRampValidationForm);
			if (this.m_listStairsGroups.Count == 0 && this.m_listRampGroups.Count == 0)
			{
				YJKMessageBox.Information("所有校验都已完成，不存在不符合标准的楼梯。");
			}
			else
			{
				StairsRampValidationResult stairsRampValidationResult = new StairsRampValidationResult(this.m_CmdData, this.m_listStairsGroups, this.m_listRampGroups);
				stairsRampValidationResult.Show(stairsRampValidationForm._hWndStairsRampValidationForm);
				for (;;)
				{
					stairsRampValidationResult.ResetContinueBreak();
					try
					{
						this.m_UIDoc.Selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1);
						continue;
					}
					catch (Exception ex)
					{
						if (!(ex is Autodesk.Revit.Exceptions.OperationCanceledException))
						{
							throw ex;
						}
						if (!stairsRampValidationResult.IfBreak)
						{
							continue;
						}
						if (stairsRampValidationResult.IfManualEsc)
						{
							stairsRampValidationResult.Close();
						}
					}
					break;
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private Result ValidationByProject(StairsRampValidationForm dlg)
		{
			List<BaseLinkDocumentResultBean> list = new List<BaseLinkDocumentResultBean>();
			ElementClassFilter filter = new ElementClassFilter(typeof(Stairs));
			FilteredElementCollectorLinkDocument filteredElementCollectorLinkDocument = new FilteredElementCollectorLinkDocument(this.m_Doc);
			filteredElementCollectorLinkDocument.WherePass(filter);
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in filteredElementCollectorLinkDocument.ToBeans())
			{
				if (baseLinkDocumentResultBean.LstParentRevitLinkInstance.Count <= 1)
				{
					list.Add(baseLinkDocumentResultBean);
				}
			}
			if (list.Count > 0)
			{
				this.StairsValidation(list, dlg);
			}
			ICollection<Element> collection = new FilteredElementCollector(this.m_Doc).OfClass(typeof(Group)).ToElements();
			if (0 < collection.Count)
			{
				this.RampValidation(collection, dlg);
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void StairsValidation(List<BaseLinkDocumentResultBean> ListStairs, StairsRampValidationForm dlg)
		{
			string text = null;
			string text2 = null;
			List<StairsResult> list = new List<StairsResult>();
			List<StairsDataType> stairsCheckItem = dlg.GetStairsCheckItem();
			Transaction transaction = new Transaction(this.m_Doc, "涉及到拷贝");
			transaction.Start();
			try
			{
				StairsClearHeightMgr stairsClearHeightMgr = new StairsClearHeightMgr(this.m_Doc, null);
				List<BaseLinkDocumentResultBean> list2 = new List<BaseLinkDocumentResultBean>();
				foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in ListStairs)
				{
					if (baseLinkDocumentResultBean.LinkeInstanceId != -1)
					{
						list2.Add(baseLinkDocumentResultBean);
					}
				}
				ProgressBarForm progressBarForm = null;
				if (list2.Count > 10)
				{
					progressBarForm = new ProgressBarForm(list2.Count, ProgressBarStyle.Blocks, true);
					progressBarForm.Text = "链接文件中楼梯校验进度显示";
					progressBarForm.ShowInTaskbar = false;
					progressBarForm.Show(CmdStairsRampValidation._hWndRevit);
				}
				List<ElementId> list3 = new List<ElementId>();
				Dictionary<ElementId, BaseLinkDocumentResultBean> dictionary = new Dictionary<ElementId, BaseLinkDocumentResultBean>();
				foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean2 in ListStairs)
				{
					dictionary.Add(baseLinkDocumentResultBean2.UseElement.Id, baseLinkDocumentResultBean2);
					if (baseLinkDocumentResultBean2.LinkeInstanceId == -1)
					{
						list3.Add(baseLinkDocumentResultBean2.UseElement.Id);
					}
					else
					{
						if (progressBarForm != null)
						{
							progressBarForm.RefreshProgressBar();
							if (progressBarForm.m_stopTag)
							{
								return;
							}
						}
						CopyPasteOptions copyPasteOptions = new CopyPasteOptions();
						List<ElementId> list4 = new List<ElementId>();
						list4.Add(baseLinkDocumentResultBean2.UseElement.Id);
						ICollection<ElementId> source = ElementTransformUtils.CopyElements(baseLinkDocumentResultBean2.UseElement.Document, list4, this.m_Doc, baseLinkDocumentResultBean2.GetTotalTransform(), copyPasteOptions);
						list3.Add(source.First<ElementId>());
					}
				}
				stairsClearHeightMgr.InitData(StairsClearHeightMgr.InitDataType.INIT_CHKCLEARHEIGHT, list3);
				int num = 0;
				foreach (ElementId elementId in list3)
				{
					text = null;
					text2 = null;
					num++;
					if (this.ValidStairs(this.m_Doc, elementId))
					{
						bool flag = this.ValidationClearHeight(this.m_Doc, elementId);
						List<ValidatingData> list5 = new List<ValidatingData>();
						ValidatingData item = default(ValidatingData);
						List<double> runWidth = StairsData.GetRunWidth(this.m_Doc, elementId);
						double num2 = double.MinValue;
						foreach (double num3 in runWidth)
						{
							if (num2 < num3)
							{
								num2 = num3;
							}
						}
						using (List<StairsDataType>.Enumerator enumerator4 = stairsCheckItem.GetEnumerator())
						{
							while (enumerator4.MoveNext())
							{
								switch (enumerator4.Current)
								{
								case StairsDataType.SDT_RunWidth:
									item.Type = DataType.DT_RunWidth;
									item.Name = "梯段宽度";
									for (int i = 0; i < runWidth.Count; i++)
									{
										item.Value = runWidth.ElementAt(i);
										list5.Add(item);
									}
									break;
								case StairsDataType.SDT_TreadHeight:
									item.Type = DataType.DT_TreadHeight;
									item.Name = "踏步高度";
									item.Value = StairsData.GetTreadHeight(this.m_Doc, elementId);
									list5.Add(item);
									break;
								case StairsDataType.SDT_TreadDepth:
									item.Type = DataType.DT_TreadDepth;
									item.Name = "踏步宽度";
									item.Value = StairsData.GetTreadDepth(this.m_Doc, elementId);
									list5.Add(item);
									break;
								case StairsDataType.SDT_LandWidth:
								{
									item.Type = DataType.DT_LandWidth;
									item.Name = "休息平台净宽";
									List<double> landWidth = StairsData.GetLandWidth(this.m_Doc, elementId);
									for (int j = 0; j < landWidth.Count; j++)
									{
										item.Value = landWidth.ElementAt(j);
										list5.Add(item);
									}
									break;
								}
								case StairsDataType.SDT_RunHeight:
									if (flag)
									{
										text = StairsData.GetStairsHeight(stairsClearHeightMgr, elementId);
									}
									break;
								case StairsDataType.SDT_LandHeight:
									if (flag)
									{
										text2 = StairsData.GetLandHeight(stairsClearHeightMgr, elementId);
									}
									break;
								}
							}
						}
						string text3 = FormParamManager.GetValidatingData(list5, dlg.GetBuildTypeName(), num2);
						if (text != null)
						{
							text3 = text3 + text + "\n";
						}
						if (text2 != null)
						{
							text3 = text3 + text2 + "\n";
						}
						if (text3 != null)
						{
							StairsResult stairsCompareData = this.GetStairsCompareData(this.m_Doc, elementId, text3);
							int num4 = num - 1;
							if (dictionary[elementId].LinkeInstanceId != -1)
							{
								stairsCompareData.m_idLinkInstance = new ElementId(dictionary[elementId].LinkeInstanceId);
							}
							stairsCompareData.m_idStairs = dictionary[elementId].UseElement.Id;
							list.Add(stairsCompareData);
						}
					}
				}
				transaction.RollBack();
				if (list.Count != 0)
				{
					this.m_listStairsGroups = this.GetStairsGroups(list);
				}
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private void RampValidation(ICollection<Element> rampElements, StairsRampValidationForm dlg)
		{
			string text = null;
			List<RampResult> list = new List<RampResult>();
			List<RampDataType> rampCheckItem = dlg.GetRampCheckItem();
			foreach (Element element in rampElements)
			{
				Group group = element as Group;
				if (group.Name.Contains("无障碍坡道"))
				{
					int rampSlope = RampData.GetRampSlope(group);
					List<RampValidationData> list2 = new List<RampValidationData>();
					RampValidationData item = default(RampValidationData);
					using (List<RampDataType>.Enumerator enumerator2 = rampCheckItem.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							switch (enumerator2.Current)
							{
							case RampDataType.RDT_RampSlope:
								item.Type = RampDataType.RDT_RampSlope;
								item.Name = "坡道坡度";
								item.Value = RampData.GetRampSlope(group);
								list2.Add(item);
								break;
							case RampDataType.RDT_RampMaxHeight:
								item.Type = RampDataType.RDT_RampMaxHeight;
								item.Name = "坡道最大高度";
								item.Value = RampData.GetRampMaxHeight(group);
								item.Slope = rampSlope;
								list2.Add(item);
								break;
							case RampDataType.RDT_RampWidth:
								item.Type = RampDataType.RDT_RampWidth;
								item.Name = "坡道宽度";
								item.Value = RampData.GetRampWidth(group);
								item.Slope = rampSlope;
								list2.Add(item);
								break;
							case RampDataType.RDT_RampLength:
							{
								item.Type = RampDataType.RDT_RampLength;
								item.Slope = rampSlope;
								List<int> rampLength = RampData.GetRampLength(group);
								for (int i = 0; i < rampLength.Count; i++)
								{
									string name = "坡段" + (i + 1) + "长度";
									item.Name = name;
									item.Value = rampLength.ElementAt(i);
									list2.Add(item);
								}
								break;
							}
							case RampDataType.RDT_LandLength:
								item.Type = RampDataType.RDT_LandLength;
								item.Name = "平台水平长度";
								item.Value = RampData.GetLandLength(group);
								item.Slope = rampSlope;
								list2.Add(item);
								break;
							}
						}
					}
					text = RampData.GetValidatingData(list2);
				}
				if (text != null)
				{
					list.Add(this.GetRampCompareData(this.m_Doc, element, text));
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			this.m_listRampGroups = this.GetRampGroups(list);
		}

		private bool IsStairsOverSevenFloor(ElementId idStairs)
		{
			List<Level> sortLevels = StairsRampValidationManager.GetSortLevels(this.m_Doc, double.MinValue, double.MaxValue);
			List<Level> list = new List<Level>();
			int count = sortLevels.Count;
			for (int i = 0; i < count; i++)
			{
				Level level = sortLevels.ElementAt(i);
				if (0.0 <= level.Elevation)
				{
					list.Add(level);
				}
			}
			if (7 > list.Count)
			{
				return false;
			}
			double elevation = list.ElementAt(6).Elevation;
			Stairs stairs = this.m_Doc.GetElement(idStairs) as Stairs;
			return elevation <= stairs.BaseElevation;
		}

		private bool ValidStairs(Autodesk.Revit.DB.Document document, ElementId idStairs)
		{
			bool result = false;
			Stairs stairs = document.GetElement(idStairs) as Stairs;
			if (stairs != null)
			{
				result = stairs.GetParameter("多层顶部标高").AsValueString().Contains("无");
			}
			return result;
		}

		private bool ValidationClearHeight(Autodesk.Revit.DB.Document document, ElementId idStairs)
		{
			bool result = false;
			Stairs stairs = document.GetElement(idStairs) as Stairs;
			if (stairs != null)
			{
				ElementId typeId = stairs.GetTypeId();
				string name = (this.m_Doc.GetElement(typeId) as StairsType).Name;
				result = (!name.Contains("三角楼梯") && !name.Contains("弧形楼梯") && !name.Contains("矩形转角楼梯"));
			}
			return result;
		}

		private List<string> GetWarnInfo(string sWarnInfo)
		{
			List<string> list = new List<string>();
			foreach (string item in sWarnInfo.Split(new char[]
			{
				'\n'
			}))
			{
				list.Add(item);
			}
			return list;
		}

		private StairsResult GetStairsCompareData(Autodesk.Revit.DB.Document document, ElementId idStairs, string sStairsWarnInfo)
		{
			return new StairsResult
			{
				m_idStairs = idStairs,
				m_dStairsHeight = StairsData.GetStairsSelfHeight(document, idStairs),
				m_dTreadHeight = StairsData.GetTreadHeight(document, idStairs),
				m_dTreadDepth = StairsData.GetTreadDepth(document, idStairs),
				m_listRunWidth = StairsData.GetRunWidth(document, idStairs),
				m_listWarnInfo = this.GetWarnInfo(sStairsWarnInfo)
			};
		}

		private List<List<StairsResult>> GetStairsGroups(List<StairsResult> listStairsAllData)
		{
			List<List<StairsResult>> list = new List<List<StairsResult>>();
			list.Add(new List<StairsResult>
			{
				listStairsAllData.ElementAt(0)
			});
			for (int i = 1; i < listStairsAllData.Count; i++)
			{
				StairsResult stairsResult = listStairsAllData.ElementAt(i);
				int j = 0;
				while (j < list.Count)
				{
					StairsResult stairsResult2 = list.ElementAt(j).ElementAt(0);
					List<double> list2 = new List<double>();
					list2.AddRange(stairsResult2.m_listRunWidth);
					if (stairsResult.m_dStairsHeight.ToString("f2").Contains(stairsResult2.m_dStairsHeight.ToString("f2")) && stairsResult.m_dTreadHeight.ToString("f2").Contains(stairsResult2.m_dTreadHeight.ToString("f2")) && stairsResult.m_dTreadDepth.ToString("f2").Contains(stairsResult2.m_dTreadDepth.ToString("f2")) && stairsResult.m_listRunWidth.Count == stairsResult2.m_listRunWidth.Count)
					{
						bool flag = false;
						for (int k = 0; k < stairsResult.m_listRunWidth.Count; k++)
						{
							double num = stairsResult.m_listRunWidth.ElementAt(k);
							for (int l = 0; l < list2.Count; l++)
							{
								if (num == list2.ElementAt(l))
								{
									flag = true;
									list2.RemoveAt(l);
									break;
								}
								flag = false;
							}
							if (!flag)
							{
								break;
							}
						}
						if (flag)
						{
							list.ElementAt(j).Add(stairsResult);
							break;
						}
						list.Add(new List<StairsResult>
						{
							stairsResult
						});
						break;
					}
					else
					{
						if (j == list.Count - 1)
						{
							list.Add(new List<StairsResult>
							{
								stairsResult
							});
							break;
						}
						j++;
					}
				}
			}
			return list;
		}

		private RampResult GetRampCompareData(Autodesk.Revit.DB.Document document, Element elemRamp, string sRampWarnInfo)
		{
			return new RampResult
			{
				m_idRamp = elemRamp.Id,
				m_nRampSlope = RampData.GetRampSlope(elemRamp),
				m_nRampMaxHeight = RampData.GetRampMaxHeight(elemRamp),
				m_nRampWidth = RampData.GetRampWidth(elemRamp),
				m_nLandLength = RampData.GetLandLength(elemRamp),
				m_listRampLength = RampData.GetRampLength(elemRamp),
				m_listWarnInfo = this.GetWarnInfo(sRampWarnInfo)
			};
		}

		private List<List<RampResult>> GetRampGroups(List<RampResult> listRampAllData)
		{
			List<List<RampResult>> list = new List<List<RampResult>>();
			list.Add(new List<RampResult>
			{
				listRampAllData.ElementAt(0)
			});
			for (int i = 1; i < listRampAllData.Count; i++)
			{
				RampResult rampResult = listRampAllData.ElementAt(i);
				int j = 0;
				while (j < list.Count)
				{
					RampResult rampResult2 = list.ElementAt(j).ElementAt(0);
					List<int> list2 = new List<int>();
					list2.AddRange(rampResult2.m_listRampLength);
					if (rampResult.m_nRampSlope == rampResult2.m_nRampSlope && rampResult.m_nRampMaxHeight == rampResult2.m_nRampMaxHeight && rampResult.m_nRampWidth == rampResult2.m_nRampWidth && rampResult.m_nLandLength == rampResult2.m_nLandLength && rampResult.m_listRampLength.Count == rampResult2.m_listRampLength.Count)
					{
						bool flag = false;
						for (int k = 0; k < rampResult.m_listRampLength.Count; k++)
						{
							int num = rampResult.m_listRampLength.ElementAt(k);
							for (int l = 0; l < list2.Count; l++)
							{
								if (num == list2.ElementAt(l))
								{
									flag = true;
									list2.RemoveAt(l);
									break;
								}
								flag = false;
							}
							if (!flag)
							{
								break;
							}
						}
						if (flag)
						{
							list.ElementAt(j).Add(rampResult);
							break;
						}
						list.Add(new List<RampResult>
						{
							rampResult
						});
						break;
					}
					else
					{
						if (j == list.Count - 1)
						{
							list.Add(new List<RampResult>
							{
								rampResult
							});
							break;
						}
						j++;
					}
				}
			}
			return list;
		}

		public static List<Level> GetSortLevels(Autodesk.Revit.DB.Document doc, double bottom, double top)
		{
			List<Level> list = new List<Level>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Level)).ToElements())
			{
				Level level = element as Level;
				double elevation = level.Elevation;
				if (elevation >= bottom && elevation <= top)
				{
					list.Add(level);
				}
			}
			list.Sort(new LevelComparer());
			return list;
		}

		private ExternalCommandData m_CmdData;

		private UIApplication m_UIApp;

		private UIDocument m_UIDoc;

        private Autodesk.Revit.ApplicationServices.Application m_App;

		private Document m_Doc;

		private List<List<RampResult>> m_listRampGroups;

		private List<List<StairsResult>> m_listStairsGroups;

		private ComponentTypeManager m_ComponentTypeManager;
	}
}
